<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\InvalidRequestException;
use App\Http\Requests\ApplyRefundRequest;
use App\Http\Requests\OrderRequest;
use App\Http\Requests\ReceiptOrderRequest;
use App\Http\Requests\ReviewOrderRequest;
use App\Models\Brand;
use App\Models\Category;
use App\Models\CouponCode;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\UserAddress;
use App\Services\OrderService;
use Carbon\Carbon;
use Illuminate\Http\Request;

class OrdersController extends Controller
{

    // 创建订单
    public function store(OrderRequest $request, OrderService $orderService)
    {
        $user = $request->user();
        $remark = $request->input('remark');
        $items = $request->input('items');
        $address = UserAddress::query()->find($request->input('address_id'));
        $coupon = $request->has("coupon")
            ? CouponCode::query()->where("code", $request->input("coupon"))->first()
            : "";
        $order = $orderService->store($user, $address, $remark, $items, $coupon);

        return $this->success($order);
    }
    
    // 显示订单列表
    public function index(Request $request)
    {
        $builder = Order::query()
            ->with(['items.product', 'items.productSku'])
            ->where('user_id', $request->user()->id)
            ->orderBy('created_at', 'desc');

        // 根据订单类型获取订单列表
        if ($type = intval($request->input('type'))) {
            $typeMap = [
                1 => '待付款订单',
                2 => '待发货订单',
                3 => '待收货订单',
                4 => '待评价订单',
                5 => '退款订单'
            ];

            if (!in_array($type, array_keys($typeMap))) {
                return $this->failed('请求类型异常');
            }

            switch ($type) {
                case 1:
                    // 获取待付款订单列表
                    $builder = $builder->where('closed', false)->whereNull('paid_at');
                    break;
                case 2:
                    // 获取待发货订单
                    $builder = $builder->where('closed', false)
                        ->whereNotNull('paid_at')
                        ->where('ship_status', Order::SHIP_STATUS_PENDING)
                        ->where('refund_status', Order::REFUND_STATUS_PENDING);
                    break;
                case 3:
                    // 待收货
                    $builder = $builder->whereNotNull('paid_at')
                        ->where('closed', false)
                        ->where('ship_status', Order::SHIP_STATUS_DELIVERED);
                    break;
                case 4:
                    // 待评价订单
                    $builder = $builder->where('closed', true)
                        ->whereNotNull('paid_at')
                        ->where('ship_status', Order::SHIP_STATUS_RECEIVED)
                        ->whereNotNull('reviewed');
                    break;
                case 5:
                    // 退款订单
                    $builder = $builder->whereNotNull('paid_at')
                        ->where('refund_status', '!=', Order::REFUND_STATUS_PENDING);
                    break;
                case 6:
                    // 获取收货订单
                    $builder = $builder->where('closed', true)
                        ->whereNotNull('paid_at')
                        ->where('ship_status', Order::SHIP_STATUS_RECEIVED);
                    break;
                default:
                    break;
            }
        }

        // 根据订单号获取
        if ($search = $request->input('search')) {
            $builder = $builder->where('no', 'like', '%'. $search . '%');
        }

        $orders = $builder->paginate(10);

        return $this->success($orders);
    }

    // 订单详情
    public function show(Order $order)
    {
        $this->authorize('own', $order);

        return $this->success($order->load(['items.productSku', 'items.product', 'couponCode']));
    }

    // 获取简单的订单信息
    public function simpleShow(Order $order)
    {
        $this->authorize('own', $order);
        return $this->success($order->load('items'));
    }

    // 预加载创建订单所需信息
    public function preview(Request $request)
    {
        $user = $request->user();

        // 地址信息
        $data['address'] = $user->addresses()->orderBy('last_used_at', 'desc')->first();

        // 获取用户要购买的商品
        $cartItems = $user
            ->cartItems()
            ->with(['productSku', 'productSku.product'])
            ->whereIn('id', $request->input('cart_ids'))
            ->get();

        // 这里的key应该返回cart_items好一点, 主要是我懒得改前端了
        $data['product_skus'] = $cartItems;

        // 通过商品id进行分组计算每个分组的总价格
        $productGroup = [];
        foreach ($cartItems->groupBy("productSku.product_id") as $product_id => $value) {
            $productGroup[$product_id] = $this->totalAmount($value);
        }

        // 相同品牌的总价格
        $brandGroup = [];
        foreach ($cartItems->groupBy("productSku.product.brand_id") as $brand_id => $value) {
            $brandGroup[$brand_id] = $this->totalAmount($value);
        }

        // 相同分类的总价格
        $categoryGroup = [];
        foreach ($cartItems->groupBy("productSku.product.category_id") as $category_id => $value) {
            $categoryGroup[$category_id] = $this->totalAmount($value);
        }

        // 计算商品总金额
        $sumTotal = $this->totalAmount($cartItems);

        // 获取用户领取的优惠券, 给每个优惠券都添加是否可用的标识, 标识名称为"can_use"
        $data['coupon_codes'] = $request->user()->couponCodes()
            ->where('not_before', "<", Carbon::now())
            ->where('not_after', ">", Carbon::now())
            ->where('enabled', true)
            ->get()
            ->groupBy("coupon_codeable_type")
            ->each(function ($collections, $type) use ($user, $sumTotal, $productGroup, $brandGroup, $categoryGroup) {
                switch ($type) {
                    case Brand::class :  // 品牌优惠券
                        $collections->each(function ($value) use ($user, $brandGroup) {
                            if (in_array($value->coupon_codeable_id, array_keys($brandGroup))) {
                                $total = $brandGroup[ $value->coupon_codeable_id ];
                                $value->can_use = $value->checkAvailableReturnBoolean($user, $total);
                            } else {
                                $value->can_use = false;
                            }
                            return $value;
                        });
                        return $collections;
                        break;
                    case Product::class :  // 商品优惠券
                        $collections->each(function ($value) use ($user, $productGroup) {
                            if (in_array($value->coupon_codeable_id, array_keys($productGroup))) {
                                $total = $productGroup[$value->coupon_codeable_id];
                                $value->can_use = $value->checkAvailableReturnBoolean($user, $total);
                            } else {
                                $value->can_use = false;
                            }
                            return $value;
                        });
                        return $collections;
                        break;
                    case Category::class :  // 分类优惠券
                        $collections->each(function ($value) use ($user, $categoryGroup) {
                            if (in_array($value->coupon_codeable_id, array_keys($categoryGroup))) {
                                $total = $categoryGroup[$value->coupon_codeable_id];
                                $value->can_use = $value->checkAvailableReturnBoolean($user, $total);
                            } else {
                                $value->can_use = false;
                            }
                            return $value;
                        });
                        return $collections;
                        break;
                    case "":  // 全场优惠券
                        $collections->each(function ($value) use ($user, $sumTotal) {
                            // 判断全场劵是否可以用
                            $value->can_use = $value->checkAvailableReturnBoolean($user, $sumTotal);
                            return $value;
                        });
                        return $collections;
                        break;
                    default:
                        throw new InvalidRequestException("未定义的优惠券多态类型:" . $type);
                        break;
                }
            })->flatten();

        return $this->success($data);
    }

    // 计算总价格
    private function totalAmount($collections)
    {
        return $collections->reduce(function ($carry, $value) {
            return $carry + $value->productSku->price * $value->amount;
        });
    }

    // 申请退款
    public function applyRefund(Order $order, ApplyRefundRequest $request)
    {
        // 校验订单是否属于当前用户
        $this->authorize('own', $order);

        // 判断订单是否付款
        if (!$order->paid_at) {
            throw new InvalidRequestException('该订单未支付, 不可退款');
        }

        // 判断订单状态是否正确
        if ($order->refund_status !== Order::REFUND_STATUS_PENDING) {
            throw new InvalidRequestException('订单已经申请过退款, 请勿重复操作');
        }

        // 将用户输入的退款理由放到订单的extra字段中
        $extra = $order->extra ?: [];
        $extra['refund_reason'] = $request->input('reason');

        // 将订单状态修改为已经申请退款状态
        $order->update([
            'extra' => $extra,
            'refund_status' => Order::REFUND_STATUS_APPLIED
        ]);

        return $this->message('已申请退款');
    }
    
    // 搜索订单
    public function searchOrderByNo(Request $request)
    {
        $no = "%" . $request->input("no") . "%";
        $orders = $request->user()->orders()->with(["items", "items.productSku", "items.product"])->where("no", "like", $no)->get();
        return $this->success($orders);
    }

    // 确认收货
    public function receipt(ReceiptOrderRequest $request)
    {
        $order = Order::query()->find($request->input("order_id"));
        $order->update([
            'ship_status' => Order::SHIP_STATUS_RECEIVED, // 用户确认收货
            'closed' => true // 订单关闭
        ]);
        return $this->message("确认收货成功~");
    }

    // 评价订单, 批量评价订单
//    public function review(ReviewOrderRequest-old $request)
//    {
//        $orderItemsIds = $request->input('order_items_ids');
//        OrderItem::query()->whereIn('id', $orderItemsIds)->update([
//            'review' => $request->input('review'),
//            'reviewed_at' => Carbon::now()
//        ]);
//
//        return $this->message("评价订单成功");
//    }

    // 评价订单, 批量评价订单
    public function review(ReviewOrderRequest $request)
    {
        $orderItems = $request->input('order_items');

        $isReview = false;
        // 如果都已经评论了 orders表对应的字段改为true
        foreach ($orderItems as $item) {
            $orderItem = OrderItem::query()->where('id', $item['id'])->first();
            // 所有订单项只能评论一次
            if (!$orderItem->reviewed_at) {
                $isReview = true;
                $NotEvaluated[] = $orderItem;
                // 更新订单项的评论
                $orderItem->update([
                    'review' => $item['review'],
                    'reviewed_at' => Carbon::now()
                ]);
                // 判断当前订单下的所有订单项是否都已经评论了
                if (OrderItem::query()->where("order_id", $orderItem->order_id)->whereNull("reviewed_at")->doesntExist()) {
                    // 都评论了,把reviewed改为true
                    Order::query()->where('id', $orderItem->order_id)->update([
                        'reviewed' => true
                    ]);
                }
            }
        }

        if (!$isReview) {
            return $this->failed('你已经评论过了');
        }

        return $this->success('评论成功');
    }

}
